<html>
<head>
<title>README</title>
</head>
<body>

<center><h1>Ketchup4j README</h1></center>

<h2>License/Warranty</h2>

The core files included in this package are covered by a LGPL3 license;
the test/performance files are covered by a BSD license (see the note for the
explanation).<br>
<i>Please respect them.</i>
<p/>
This project comes with no warranty, so if your computer explodes or nasty things happen
because of having too much fun using Ketchup4j or more realistically if Ketchup4j has some horrible 
bug, the author is not responsible for what happened.
Actually, if your computer explodes, it could be a very interesting case.

<h2>Instructions</h2>

To use a cache, just create an instance, assigning (where needed/allowed):<ul>
<li><b>Cache id</b> A unique id for the cache</li>
<li><b>idleTime</b> the maximum time a cached object is allowed to live, from 
	its last insertion (put) in the cache. specify <tt>ICache.IDLETIME_UNLIMITED</tt> 
	for unlimited idleTime.</li>
<li><b>maxElements</b> Maximum number of objects to be hold in the cache. specify 
	<tt>ICache.ELEMENTS_UNLIMITED</tt> for unlimited objects.</li>
<li><b>maxMemSize</b> Maximum indicative size in bytes of the sum of all cached
	objects. Specify <tt>ICache.MAXSIZE_UNLIMITED</tt> for unlimited size.<br>
	Currently enabled only for LRUCache.</li>
<li><b>referenceType</b> Type of references to be used for the cache. 
	<tt>REF_STRONG</tt> makes the cache to use strong references;<br/>
	<tt>REF_MIXED</tt> uses strong references too, but when an object is going to be 
	evicted from the cache because of maximum number of objects of maximum 
	memory reached, instead of being dropped, it is moved in a soft referenced 
	objects pool. For this reason, <tt>REF_MIXED</tt> cannot be used with 
	<tt>ICache.ELEMENTS_UNLIMITED</tt></li> 
</ul>

<h2>Warnings!</h2>

<b>Every cache must be closed</b> (<tt>ICache.close()</tt>) if you aren't using it anymore 
and you're dropping all the references; otherwise the CacheCleaner still keeps the 
reference and the cache won't be GCed.<br>
Warning: it is still possible to use a cache after closing it, but it will not be
cleaned. 
<p>
<b>It is illegal to put a null value</b> (<tt>cache.put(objectId, null)</tt>), because it
is wasteful and meaningless. If anyway you need to emulate this, just use the
remove command (<tt>cache.remove(objectId)</tt>)
<p>
<b>Cache maximum size it not guaranteed to be stricly under the imposed limit</b>,
because it is cleaned by the CacheCleaner object.

<h2>Updates</h2>
The cache is currently being de-optimized ;-) but it is stable.<br>
Two interesting algorithmical optimizations is on the way: join of the Strong
refererence pool with the soft one with a custom LinkedHashMap, and a
TreeMap ordered by value, via a custom Red/Black binary tree.
<p>
Last revisions:<ul>
<li><b>20070822:</b> Added memory limiter to LRUCache.</li>
</ul>

<h2>Experiments on performance</h2>

Canonical modifications for speed gain and concrete results:
<ul>
<li><b>Inlining:</b> A big speed gain has been obtained by manually inlining some methods in the
	cache objects. This means that is not true that the JVM is <i>always</i> capable 
	of inlining where/when is produtive to do so</li>
<li><b>Removal of getters and setters:</b> only a minor speed increase, and in a few cases</li>
<li><b>Unsubclassing/finalizing:</b>Making LFUCacheObject a standalone class and
	adding the final modifier to the methods, gave negliglible gain</li>
</ul>

Algorithmical modifications:
<ul>
<li><b>Iteration via array of a set:</b> Cleaning the pool via copying the entries to an array, iterating it and removing
	invalid objects is not blocking, but is slower (especially for ordered collections)
	than using an iterator and its remove() function, because it doesn't involve the 
	lookup of the objects inside the pool hashmap.<br>
	Personally I prefer to give longer timeslices to cleaning instead of making
	every possible effort to spread it over the time: consider that yield()
	wastes time because of context switching.</li>
</ul>

Performance testing package:
<p/>
The included performance tests are non-meaninful for performance research
because: 1. doesn't make any sense to compare to a enterprise-functional cache
2. their formulation is not a valid test-case.<br/>
Anyway, they can be useful for coding-level profiling.<br>
Another cache is used for reference (ehcache); other common open source caches 
(oscache, jcs) has been excluded because they are too boring to configure.

<h2>Interesting stuff</h2>
Jakarta Commons Collection's ReferenceMap purge the GCed entries using subclasses
of Reference which keep the key object (the hash index, in that case).
The same could be applied here, but the cost of N removes would be more or less
the same as iterating the set by the CacheCleaner.<br>
A really cool optimization would be to join the pool and softPool in some way.

<h2>Updates</h2>
Mon 20070821<ul>
<li>Softreferences can become problematic in corner cases (too many instantiations
	in a short timeframe): added limit.</li>
</ul>

<h2>End words</h2>
Many thanks to the original author, Yuriy Stepovoy, for the original release!
The current release is a rewrite from scratch, so it's covered by the LGL3
license.<br>
The Tests and the performance tester instead are just modifications, so they are 
covered by the original BSD license).
</body>
</html>